package com.e3.template.tgf;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.e3.web.core.model.SuperModel;
import com.e3.web.widget.client.MyField;
import com.e3.web.widget.model.ListTypeModel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;

public abstract class TGFFormPanel<D extends SuperModel> extends LayoutContainer{
	
	private Map<String,Field<?>> formFieldMaps = new HashMap<String,Field<?>>();
	
	private boolean formReadonly = false;
	
	private D initedModel;
	
	private FormData formData = new FormData("95%");
	
	private int labelWidth;
	
	public void setFormValue(D model){
		initedModel = model;
		if(model == null){
			clearFormData();
			return;
		}
		doSetFormValue(model);
	}
	
	protected void doSetFormValue(D model){
		Field<?>[] fields = new Field<?>[formFieldMaps.values().size()];
		formFieldMaps.values().toArray(fields);
		for (Field<?> field : fields) {
			MyField<?> myField = (MyField<?>)field;
			String name = field.getName();
			Object value = model.get(name);
			myField.setFieldValue(value);
		}
	}

	public D getFormValue(){
		D model = initedModel;
		if(model == null){
			model = createModelInstance();
		}
		
		Field<?>[] fields = new Field<?>[formFieldMaps.values().size()];
		formFieldMaps.values().toArray(fields);
		for (Field<?> field : fields) {
			MyField<?> myField = (MyField<?>)field;
			String name = field.getName();
			Object value = myField.getFieldValue();
			setModelValue(model, name, value);
		}
		return model;
	}

	public void setFormReadonly(boolean formReadonly) {
		this.formReadonly = formReadonly;
		if(isRendered()){
			Iterator<String> names = formFieldMaps.keySet().iterator();
			while(names.hasNext()){
				String key = names.next();
				Field<?> field = formFieldMaps.get(key);
				field.setReadOnly(formReadonly);
			}
		}
	}
	
	protected FormPanel createSingleFormPanel(){
		FormPanel formPanel = new FormPanel();
		formPanel.setHeaderVisible(false);
		
		int labelWidth = getLabelWidth();
		if(labelWidth>0){
			formPanel.setLabelWidth(labelWidth);
		}
		return formPanel;
	}

	protected void initFormPanel(FormPanel formPanel,List<Field<?>> fields) {
		if(fields!=null&&fields.size()>0){
			for (Field<?> field : fields) {
				formPanel.add(field,formData);
				String name = field.getName();
				formFieldMaps.put(name, field);
			}
		}
		setFormReadonly(formReadonly);
	}
	
	protected void initFormPanel(FormPanel formPanel,Map<Integer,List<Field<?>>> colFields) {
		LayoutContainer main = new LayoutContainer();
		main.setLayout(new ColumnLayout());
		
		List<Integer> keys = new ArrayList<Integer>(colFields.size());
		keys.addAll(colFields.keySet());
		Collections.sort(keys);
		
		int size = 0;
		for (Integer key : keys) {
			List<Field<?>> fields = colFields.get(key);
			if(fields.size()>1){
				size ++;
			}
			if(fields!=null&&fields.size()>0){
				for (Field<?> field : fields) {
					String name = field.getName();
					formFieldMaps.put(name, field);
				}
			}
		}
		
		List<LayoutContainer> lcs = new ArrayList<LayoutContainer>(size);
		List<Field<?>> singleFields = new ArrayList<Field<?>>();
		for (Integer key : keys) {
			List<Field<?>> fields = colFields.get(key);
			if(fields.size()==1){
				singleFields.add(fields.get(0));
				continue;
			}
			LayoutContainer lc = new LayoutContainer();
			//lc.setStyleAttribute("paddingRight", "10px");
			FormLayout layout = new FormLayout();
			//layout.setLabelAlign(LabelAlign.LEFT);
			lc.setLayout(layout);
			
			for (Field<?> field : fields) {
				lc.add(field,getFormData());
			}
			lcs.add(lc);
		}
		
		for (LayoutContainer lc : lcs) {
			main.add(lc,new ColumnData(1/size));
		}
		for (Field<?> field : singleFields) {
			formPanel.add(field,getFormData());
		}
		
		setFormReadonly(formReadonly);
	}

	public Map<String, Field<?>> getFormFieldMaps() {
		return formFieldMaps;
	}
	
	public Field<?> getFormFieldByName(String name){
		return formFieldMaps.get(name);
	}

	public boolean isFormReadonly() {
		return formReadonly;
	}

	public FormData getFormData() {
		return formData;
	}

	public void setFormData(FormData formData) {
		this.formData = formData;
	}

	public int getLabelWidth() {
		return labelWidth;
	}

	public void setLabelWidth(int labelWidth) {
		this.labelWidth = labelWidth;
	}
	
	protected int getFormColumns(){
		return 1;
	}
	
	@SuppressWarnings("rawtypes")
	protected void setModelValue(D model,String name,Object value){
		if(value instanceof ListTypeModel){
			ListTypeModel ltm = (ListTypeModel)value;
			value = ltm.getValue();
		}
		model.set(name, value);
	}
	
	public abstract D createModelInstance();
	
	public abstract void clearFormData();
	
	
	
}
